#include <structures.hh>
#include <heuristics.hh>
#include <IO.hh>
#include <ExpensiveFirst.hh>

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <climits>
#include <ctime>
#include <cstdlib>

unsigned int bestCostSoFar = UINT_MAX;
std::vector < Piece* > bestSoFar;

static time_t start;

/**
 * Vérifie si la solution proposée est meilleurs que la meilleur
 * solution trouvée jusqu'à maintenant ainsi que si le programme tourne 
 * dans le limite de temps imposée
 *
 * @return true, si le programme est encore dans la limite de temps, false 
 * sinon.
 */
bool checkSolution ( 
    std::vector < Piece* > const& pieces, 
    Concert* concert,
    unsigned int timeLimit ) 
{
  unsigned int currentCost =  getCost( pieces, concert->musicians );

  if ( currentCost < bestCostSoFar ) {
    bestSoFar = std::vector< Piece* > (pieces);
    bestCostSoFar = currentCost;
  }

  time_t buffer; time(&buffer);
  return ( difftime (buffer, start) < timeLimit );
}

int main ( int argc, char** argv ) {
  time(&start);

  if(argc != 3) return 1;

  srand ( unsigned ( time (NULL) ) );

  Concert* concert = read ( std::string ( argv[1] ) );
  unsigned int allocatedTime = 0; sscanf(argv[2], "%d", &allocatedTime);
  allocatedTime -= 2; // Au cas où...

  // Test de quelques solutions que l'on sait ``bonnes''.
  checkSolution ( ExpensiveFirst (concert, &getMusicianCost1 ), concert, allocatedTime );
  checkSolution ( ExpensiveFirst (concert, &getMusicianCost2 ), concert, allocatedTime );
  checkSolution ( ExpensiveFirst (concert, &getMusicianCost3 ), concert, allocatedTime );

  std::vector < Piece* > permVector = 
    std::vector < Piece* > ( bestSoFar.begin(), bestSoFar.end() );
  while ( checkSolution ( permVector, concert, allocatedTime ) )
    std::random_shuffle (permVector.begin(), permVector.end() );

  display ( bestSoFar, concert->musicians );

  delete concert;
  return 0;
}
